﻿using com.nm.Cache;
using com.nm.db.Helper;
using com.nm.db.Models.SSO;
using com.nm.db.Models.Systems;
using com.nm.Helper;
using com.nm.interfaces;
using com.nm.library;
using com.nm.models;
using System;
using System.Linq;
using System.Net.Http;

namespace com.nm.db
{
    public class MemberShipFactory : IUserFactory
    {
        private static bool IsExist(int UserID, SysEntities dc = null)
        {
            dc = dc ?? (dc = new SysEntities());
            return dc.sys_users.Any(u => u.UserID == UserID);
        }

        private static User getUser(sys_users user)
        {
            var newUser = new User()
            {
                UserId = user.UserID,
                CreateDate = user.CreateDate ?? DateTime.Now,
                ID = Guid.NewGuid(),
                LoginId = user.LoginAccount,
                NickName = user.UserName,
                UserNo = user.UserNo,
                Tel = user.Tel,
                DeptId = user.DeptID,
                RoleName = "",
                SysType = user.SysType
            };
            return newUser;
        }

        public void DoLogin(User theUser)
        {
            UserInfo.CusIDInt = theUser.UserId;
            UserInfo.UserID = theUser.UserId.ToString();
            //var oahu = dc.wahOauthCus.FirstOrDefault(o => o.NativeCusID == theUser.CusID && o.OauthType == "3");
            //if (oahu != null) {
            //	UserInfo.OpenID = oahu.OauthCusNo;
            //	HttpContext.Current.SetCookie("OpenID", UserInfo.OpenID);
            //}
            UserInfo.UserName = string.IsNullOrWhiteSpace(theUser.NickName) ? theUser.LoginId : theUser.NickName;
            //UserInfo.IsTestUser = IsTestUser(theUser);

            OnlineUsers.AddAndRefresh();
        }

        public string GetRefreshToken(User loginUser)
        {
            var guid = Guid.NewGuid();
            RedisCache.AddInt($"rt:{guid}", loginUser.UserId, 60 * 24 * 30);
            return guid.ToString();
        }

        public int GetUserIdFromRefres(string key)
        {
            if (!RedisCache.Exists($"rt:{key}"))
            {
                Log.Error($"刷新Token已经过期{key}", "RefreshToken");
                return 0;
            }
            return RedisCache.GetInt($"rt:{key}", 0);
        }

        public User Login(string loginName, string pass)
        {
            var dc = new SysEntities();
            var reg = (dc.sys_users.FirstOrDefault(
                    u => u.PassWord == pass
                        && (u.LoginAccount == loginName || u.Tel == loginName)));
            if (reg == null)
            {
                throw new Exception("您输入的用户名或密码错误,请重新输入！");
            }
            if (!reg.IsEffective || reg.IsRemove == true)
            {
                throw new Exception("您的账号已经被禁用，请与服务人员联系！");
            }
            //TODO:其他情况，比如禁用用户
            var user = getUser(reg);

            //TODO:用户是否系统管理员
            user.RolesType = (from role in dc.sys_role
                              join userRole in dc.sys_user_role on role.ID equals userRole.RoleID
                              where role.IsRemove == false && role.IsEffective && userRole.UserID == reg.UserID
                              && role.RoleType == 9
                              select role.RoleType).Any();
            //UserInfo.UserID = user.UserId.ToString();
            //UserInfo.CusIDInt = reg.UserID;
            //UserInfo.UserImg = (from item in dc.vm_Avatar
            //                    where item.ID == user.UserId
            //                    select item.Url).FirstOrDefault();
            //UserInfo.CusType = reg.UserType.ToString();
            //UserInfo.UserName = string.IsNullOrWhiteSpace(reg.UserName)
            //    ? reg.LoginAccount
            //    : reg.UserName;

            //更新个人信息(登陆次数，上次登陆时间，最后登陆时间)
            //reg.PrvLoginDate = reg.LastLoginDate;
            //reg.LastLoginDate = DateTime.Now;
            //reg.LoginCount++;
            //reg.IP = HttpContext.Current.Request.GetClientIpAddress();
            //dc.SaveChanges();
            //TODO:HookService.Instance.Invoke((int)HookTypes.AFTER_USER_LOGIN, UserInfo.CusID, loginCount, lastLoginDate);
            OnlineUsers.AddAndRefresh();
            return user;
        }

        public User Login(string loginName, string pass, string pass2, string ip, int forceLogin = 0)
        {
            var user = new User();
            //判断是否启用了SSO
            string ssoEnable = ConfigHelper.SsoEnable;
            //如果启用，走SSO登录
            if (ssoEnable == "true")
            {
                //在这里去调用SSO提供的API登录
                string ApiHost = ConfigHelper.ApiHost;
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri(ConfigHelper.ApiHost);
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("appliation/json"));
                SsoUserInfo ssoUser = new SsoUserInfo()
                {
                    AppKey = ConfigHelper.AppKey,
                    AppSecret = ConfigHelper.AppSecret,
                    UserName = loginName,
                    Password = pass2,
                    Ip = ip,
                    ForceLogin = forceLogin,
                };
                HttpResponseMessage response = client.PostAsJsonAsync("api/sso/login", ssoUser).Result;
                if (response.IsSuccessStatusCode)
                {
                    var result = response.Content.ReadAsAsync<SsoResult>().Result;
                    //如果登录成功
                    if (result.Code == 0)
                    {
                        var dc = new SysEntities();
                        var reg = (dc.sys_users.FirstOrDefault(
                                u => u.PassWord == pass
                                    && (u.LoginAccount == loginName || u.Tel == loginName)));
                        if (reg == null)
                        {
                            throw new Exception("您输入的用户名或密码错误,请重新输入！");
                        }
                        if (!reg.IsEffective || reg.IsRemove == true)
                        {
                            throw new Exception("您的账号已经被禁用，请与服务人员联系！");
                        }
                        //TODO:其他情况，比如禁用用户
                        user = getUser(reg);

                        //TODO:用户是否系统管理员
                        user.RolesType = (from role in dc.sys_role
                                          join userRole in dc.sys_user_role on role.ID equals userRole.RoleID
                                          where role.IsRemove == false && role.IsEffective && userRole.UserID == reg.UserID
                                          && role.RoleType == 9
                                          select role.RoleType).Any();
                        UserInfo.UserID = reg.UserID.ToString();
                        UserInfo.CusIDInt = reg.UserID;
                        UserInfo.UserImg = (from item in dc.vm_Avatar
                                            where item.ID == user.UserId
                                            select item.Url).FirstOrDefault();
                        UserInfo.CusType = reg.UserType.ToString();
                        UserInfo.UserName = string.IsNullOrWhiteSpace(reg.UserName)
                            ? reg.LoginAccount
                            : reg.UserName;
                        //TODO:HookService.Instance.Invoke((int)HookTypes.AFTER_USER_LOGIN, UserInfo.CusID, loginCount, lastLoginDate);
                        OnlineUsers.AddAndRefresh();
                        user.OnlineInfo = result.Data;
                    }
                    //如果登录失败,直接弹出错误提示
                    else
                    {
                        throw new Exception(result.Message);
                    }
                }

            }
            //如果没有启用SSO，正常登录
            else
            {
                var dc = new SysEntities();
                var reg = (dc.sys_users.FirstOrDefault(
                        u => u.PassWord == pass
                            && (u.LoginAccount == loginName || u.Tel == loginName)));
                if (reg == null)
                {
                    throw new Exception("您输入的用户名或密码错误,请重新输入！");
                }
                if (!reg.IsEffective || reg.IsRemove == true)
                {
                    throw new Exception("您的账号已经被禁用，请与服务人员联系！");
                }
                //TODO:其他情况，比如禁用用户
                user = getUser(reg);

                //TODO:用户是否系统管理员
                user.RolesType = (from role in dc.sys_role
                                  join userRole in dc.sys_user_role on role.ID equals userRole.RoleID
                                  where role.IsRemove == false && role.IsEffective && userRole.UserID == reg.UserID
                                  && role.RoleType == 9
                                  select role.RoleType).Any();
                UserInfo.UserID = reg.UserID.ToString();
                UserInfo.CusIDInt = reg.UserID;
                UserInfo.UserImg = (from item in dc.vm_Avatar
                                    where item.ID == user.UserId
                                    select item.Url).FirstOrDefault();
                UserInfo.CusType = reg.UserType.ToString();
                UserInfo.UserName = string.IsNullOrWhiteSpace(reg.UserName)
                    ? reg.LoginAccount
                    : reg.UserName;
                //TODO:HookService.Instance.Invoke((int)HookTypes.AFTER_USER_LOGIN, UserInfo.CusID, loginCount, lastLoginDate);
                OnlineUsers.AddAndRefresh();
            }
            return user;
        }

        public User Login(string loginName, string userId, string token, string ip)
        {
            var user = new User();
            #region 调用SSO提供的API登录
            string ApiHost = ConfigHelper.ApiHost;
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(ConfigHelper.ApiHost);
            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("appliation/json"));
            SsoUserInfo userinfo = new SsoUserInfo()
            {
                AppKey = ConfigHelper.AppKey,
                AppSecret = ConfigHelper.AppSecret,
                Ip = ip,
                UserId = userId,
                Token = token,
            };
            HttpResponseMessage response = client.PostAsJsonAsync("api/sso/checkonline", userinfo).Result;
            if (response.IsSuccessStatusCode)
            {
                var result = response.Content.ReadAsAsync<SsoResult>().Result;
                //如果登录成功
                if (result.Code == 0)
                {
                    loginName = result.Data.UserName;
                }
                //如果登录失败,直接弹出错误提示
                else
                {
                    throw new Exception(result.Message);
                }
            }
            #endregion 调用SSO提供的API登录          
            //检测到用户已登录，此处不再验证密码
            //根据用户名获取用户其他信息
            var dc = new SysEntities();
            var reg = (dc.sys_users.FirstOrDefault(
                    u => (u.LoginAccount == loginName || u.Tel == loginName)));
            if (reg == null)
            {
                throw new Exception("您输入的用户名或密码错误,请重新输入！");
            }
            if (!reg.IsEffective || reg.IsRemove == true)
            {
                throw new Exception("您的账号已经被禁用，请与服务人员联系！");
            }
            //TODO:其他情况，比如禁用用户
            user = getUser(reg);
            //TODO:用户是否系统管理员
            user.RolesType = (from role in dc.sys_role
                              join userRole in dc.sys_user_role on role.ID equals userRole.RoleID
                              where role.IsRemove == false && role.IsEffective && userRole.UserID == reg.UserID
                              && role.RoleType == 9
                              select role.RoleType).Any();
            UserInfo.UserID = reg.UserID.ToString();
            UserInfo.CusIDInt = reg.UserID;
            UserInfo.UserImg = (from item in dc.vm_Avatar
                                where item.ID == user.UserId
                                select item.Url).FirstOrDefault();
            UserInfo.CusType = reg.UserType.ToString();
            UserInfo.UserName = string.IsNullOrWhiteSpace(reg.UserName)
                ? reg.LoginAccount
                : reg.UserName;
            OnlineUsers.AddAndRefresh();
            user.OnlineInfo = new SsoOnlineInfo()
            {
                Token = token,
                UserID = userId,
                UserName = loginName
            };
            return user;
        }

        public string GetOpenIdByUserId(int userId, int ThirdPart)
        {
            //var dc = new SysEntities();
            //return (from oua in dc.wahOauthCus
            //        where oua.OauthType == ThirdPart.ToString() && oua.NativeCusID == userId
            //        select oua.OauthCusNo)
            //    .DefaultIfEmpty("")
            //    .FirstOrDefault();
            return "";
        }

        public User GetUserByOpenId(string openId, int ThirdPart)
        {
            return GetUserByUserID(GetUserIdByOpenId(openId, ThirdPart));
        }

        public User GetUserByUserID(int userId)
        {
            var dc = new SysEntities();
            var newUser = getUser(dc.sys_users.FirstOrDefault(i => i.UserID == userId));
            return newUser;
        }

        public int GetUserIdByOpenId(string openId, int ThirdPart)
        {
            //var dc = new sys_users();
            //return (from oua in dc.wahOauthCus
            //        where oua.OauthType == ThirdPart.ToString() && oua.OauthCusNo == openId
            //        select oua.NativeCusID)
            //    .DefaultIfEmpty(0)
            //    .FirstOrDefault();
            return 0;
        }

        public void LoginOut()
        {
            RedisCache.Remove(UserInfo.UserID);
            RedisCache.Remove(UserInfo.UserCompanyId);

            OnlineUsers.Remove();
            UserInfo.UserID = null;
            UserInfo.UserName = null;
            UserInfo.UserImg = null;
            UserInfo.CusType = null;
            //UserInfo.OpenID = null;
            SessionHelper.Session.Clear();
            //HookService.Instance.Invoke((int)HookTypes.AFTER_USER_LOGOUT);
        }


        public void LoginOut(string token, string userId, string ip)
        {
            //调用API进行注销
            string ApiHost = ConfigHelper.ApiHost;
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(ConfigHelper.ApiHost);
            client.DefaultRequestHeaders.Accept.Add(
                new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("appliation/json"));
            SsoUserInfo ssoUser = new SsoUserInfo()
            {
                AppKey = ConfigHelper.AppKey,
                AppSecret = ConfigHelper.AppSecret,
                UserId = userId,
                Token = token,
                Ip = ip,
            };
            HttpResponseMessage response = client.PostAsJsonAsync("api/sso/loginout", ssoUser).Result;
            if (response.IsSuccessStatusCode)
            {
                var result = response.Content.ReadAsAsync<SsoResult>().Result;
                //如果注销成功
                if (result.Code == 0)
                {
                    OnlineUsers.Remove();
                    UserInfo.UserID = null;
                    UserInfo.UserName = null;
                    UserInfo.UserImg = null;
                    UserInfo.CusType = null;
                    //UserInfo.OpenID = null;
                    SessionHelper.Session.Clear();
                    //HookService.Instance.Invoke((int)HookTypes.AFTER_USER_LOGOUT);               
                }
                //如果登录失败,直接弹出错误提示
                else
                {
                    throw new Exception(result.Message);
                }
            }
        }

    }
}